<template>
  <div class="table-toolbar">
    <!-- 顶部左侧区域：标题 + 标题提示 -->
    <div class="flex items-center table-toolbar-left">
      <template v-if="props.title">
        <div class="table-toolbar-left-title">
          {{ props.title }}
          <n-tooltip trigger="hover" v-if="props.titleTooltip">
            <template #trigger>
              <n-icon size="18" class="ml-1 text-gray-400 cursor-pointer">
                <QuestionCircleOutlined />
              </n-icon>
            </template>
            {{ props.titleTooltip }}
          </n-tooltip>
        </div>
      </template>
      <!-- 自定义标题插槽 -->
      <slot name="tableTitle"></slot>
    </div>

    <!-- 顶部右侧区域：工具栏、斑马纹开关、刷新、密度切换、列设置（暂注释，可按需启用） -->
    <!-- <div class="flex items-center leading-none table-toolbar-right">
      <slot name="toolbar"></slot>
      <n-tooltip trigger="hover">
        <template #trigger>
          <div class="mr-2 table-toolbar-right-icon">
            <n-switch v-model:value="isStriped" @update:value="setStriped" />
          </div>
        </template>
        <span>表格斑马纹</span>
      </n-tooltip>
      <n-divider vertical />

      <n-tooltip trigger="hover">
        <template #trigger>
          <div class="table-toolbar-right-icon" @click="reload">
            <n-icon size="18">
              <ReloadOutlined />
            </n-icon>
          </div>
        </template>
        <span>刷新</span>
      </n-tooltip>

      <n-tooltip trigger="hover">
        <template #trigger>
          <div class="table-toolbar-right-icon">
            <n-dropdown
              @select="densitySelect"
              trigger="click"
              :options="densityOptions"
              v-model:value="tableSize"
            >
              <n-icon size="18">
                <ColumnHeightOutlined />
              </n-icon>
            </n-dropdown>
          </div>
        </template>
        <span>密度</span>
      </n-tooltip>
      <ColumnSetting />
    </div> -->
  </div>

  <!-- 表格主体区域 -->
  <div class="s-table">
    <n-data-table
      ref="tableElRef"
      v-bind="getBindValues"
      :striped="isStriped"
      :pagination="pagination"
      @update:page="updatePage"
      @update:page-size="updatePageSize"
      @update:checked-row-keys="(keys) => emit('update:checked-row-keys', keys)"
    >
      <!-- 透传所有自定义插槽（如列模板插槽） -->
      <template #[item]="data" v-for="item in Object.keys($slots)" :key="item">
        <slot :name="item" v-bind="data"></slot>
      </template>
    </n-data-table>
  </div>
</template>

<script lang="ts" setup>
import { ref, unref, toRaw, computed, onMounted, nextTick } from 'vue';
// 导入图标组件
import { ReloadOutlined, ColumnHeightOutlined, QuestionCircleOutlined } from '@vicons/antd';
// 导入表格上下文、hooks、组件
import { createTableContext } from './hooks/useTableContext';
import ColumnSetting from './components/settings/ColumnSetting.vue';
import { useLoading } from './hooks/useLoading';
import { useColumns } from './hooks/useColumns';
import { useDataSource } from './hooks/useDataSource';
import { usePagination } from './hooks/usePagination';
// 导入属性定义和类型
import { basicProps } from './props';
import { BasicTableProps } from './types/table';
// 导入工具函数
import { getViewportOffset } from '@/utils/domUtils';
import { useWindowSizeFn } from '@/hooks/event/useWindowSizeFn';
import { isBoolean } from '@/utils/is';
// 类型声明（适配组件引用和空值处理）
type ComponentRef = InstanceType<typeof import('naive-ui/lib/data-table/src/DataTable')> | null;
type Nullable<T> = T | null;
type Recordable = Record<string, any>;

// 表格密度选项配置
const densityOptions = [
  { type: 'menu', label: '紧凑', key: 'small' },
  { type: 'menu', label: '默认', key: 'medium' },
  { type: 'menu', label: '宽松', key: 'large' },
];

// 定义组件事件（透传分页、选中、编辑等事件）
const emit = defineEmits([
  'fetch-success',
  'fetch-error',
  'update:checked-row-keys',
  'edit-end',
  'edit-cancel',
  'edit-row-end',
  'edit-change',
]);

// 接收外部传入的属性（合并基础属性）
const props = defineProps({ ...basicProps });

// 组件内部响应式状态
const deviceHeight = ref(150); // 表格高度
const tableElRef = ref<ComponentRef>(null); // 表格DOM引用
const wrapRef = ref<Nullable<HTMLDivElement>>(null); // 容器引用
let paginationEl: HTMLElement | null; // 分页DOM元素
const isStriped = ref(props.striped || false); // 斑马纹状态
const tableData = ref<Recordable[]>([]); // 表格原始数据
const innerPropsRef = ref<Partial<BasicTableProps>>(); // 内部属性（用于动态修改）

// 合并外部属性和内部属性，作为最终属性源
const getProps = computed(() => {
  return { ...props, ...unref(innerPropsRef) } as BasicTableProps;
});

// 表格尺寸（默认中等）
const tableSize = ref(unref(getProps).size || 'medium');

// 初始化核心hooks
const { getLoading, setLoading } = useLoading(getProps); // 加载状态
const { getPaginationInfo, setPagination } = usePagination(getProps); // 分页逻辑
const { getDataSourceRef, getDataSource, getRowKey, reload } = useDataSource( // 数据逻辑
  getProps,
  { getPaginationInfo, setPagination, tableData, setLoading },
  emit
);
const { getPageColumns, setColumns, getColumns, getCacheColumns, setCacheColumnsField } = // 列逻辑
  useColumns(getProps);

// 页码切换：更新分页并重新加载数据
function updatePage(page: number) {
  setPagination({ page });
  reload();
}

// 每页条数切换：重置页码为1，更新分页并重新加载数据
function updatePageSize(pageSize: number) {
  setPagination({ page: 1, pageSize });
  reload();
}

// 密度切换：更新表格尺寸
function densitySelect(key: string) {
  tableSize.value = key;
}

// 表格尺寸计算（供表格绑定使用）
const getTableSize = computed(() => tableSize.value);

// 🌟 核心：注入多选选中框列（根据showSelection控制）
const getFinalColumns = computed(() => {
  const originalColumns = unref(getPageColumns); // 原始列配置
  const { showSelection = false, selectionProps = {} } = unref(getProps);

  // 未开启选中框时，直接返回原始列
  if (!showSelection) return originalColumns;

  // 构建选中框列（支持自定义配置：如禁用行、列宽等）
  const selectionColumn = {
    type: 'selection', // Naive-UI固定多选列类型
    key: 'table-selection', // 唯一标识，避免与其他列冲突
    width: 60, // 固定列宽，避免拉伸
    ...selectionProps, // 合并外部传入的选中框配置
  };

  // 将选中框列插入到最左侧
  return [selectionColumn, ...originalColumns];
});

// 🌟 表格最终绑定的属性（整合所有配置）
const getBindValues = computed(() => {
  const tableData = unref(getDataSourceRef); // 最终数据源
  const maxHeight = tableData.length ? `${unref(deviceHeight)}px` : 'auto'; // 动态高度

  return {
    ...unref(getProps),
    loading: unref(getLoading), // 加载状态
    columns: toRaw(unref(getFinalColumns)), // 注入选中框后的列配置
    rowKey: unref(getRowKey), // 行唯一标识（如id）
    data: tableData, // 表格渲染数据
    size: unref(getTableSize), // 表格密度
    remote: true, // 远程分页（由外部控制数据）
    'max-height': maxHeight, // 表格最大高度
    title: '', // 清空表格自带标题（由工具栏标题替代）
  };
});

// 分页配置（供表格绑定使用，透传分页信息）
const pagination = computed(() => toRaw(unref(getPaginationInfo)));

// 动态修改组件内部属性
function setProps(newProps: Partial<BasicTableProps>) {
  innerPropsRef.value = { ...unref(innerPropsRef), ...newProps };
}

// 切换斑马纹状态
const setStriped = (value: boolean) => {
  isStriped.value = value;
};

// 暴露给外部的方法（供父组件调用，如刷新、修改列等）
const tableAction = {
  reload,
  setColumns,
  setLoading,
  setProps,
  getColumns,
  getDataSource,
  getPageColumns,
  getCacheColumns,
  setCacheColumnsField,
  emit,
};

// 是否允许表格高度自适应
const getCanResize = computed(() => {
  const { canResize } = unref(getProps);
  return canResize;
});

// 计算表格自适应高度（根据视口高度动态调整）
async function computeTableHeight() {
  const table = unref(tableElRef);
  if (!table) return;
  if (!unref(getCanResize)) return;

  const tableEl = table.$el as HTMLElement;
  const headEl = tableEl.querySelector('.n-data-table-thead');
  if (!headEl) return;

  // 获取表头到视口底部的距离
  const { bottomIncludeBody } = getViewportOffset(headEl);
  const headerH = 64; // 工具栏高度
  let paginationH = 2; // 分页区域基础高度
  const marginH = 24; // 边距高度

  // 计算分页区域实际高度（若存在分页）
  if (!isBoolean(unref(pagination))) {
    paginationEl = tableEl.querySelector('.n-data-table__pagination') as HTMLElement;
    paginationH += paginationEl ? paginationEl.offsetHeight : 28;
  }

  // 计算最终表格高度（减去工具栏、分页、边距，支持偏移量配置）
  let height = bottomIncludeBody - (headerH + paginationH + marginH + (props.resizeHeightOffset || 0));
  // 限制最大高度（若外部配置了maxHeight）
  if (props.maxHeight && props.maxHeight < height) {
    height = props.maxHeight;
  }

  deviceHeight.value = height;
}

// 监听窗口大小变化，动态调整表格高度
useWindowSizeFn(computeTableHeight, 280);

// 组件挂载后，初始化表格高度
onMounted(() => {
  nextTick(() => {
    computeTableHeight();
  });
});

// 创建表格上下文（供子组件访问表格方法）
createTableContext({ ...tableAction, wrapRef, getBindValues });

// 暴露组件方法给外部（父组件可通过ref调用）
defineExpose(tableAction);
</script>

<style lang="less" scoped>
.table-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 0 16px 0;
  margin-bottom: 8px;

  &-left {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    flex: 1;

    &-title {
      display: flex;
      align-items: center;
      justify-content: flex-start;
      font-size: 16px;
      font-weight: 600;
      color: var(--text-color-primary);
    }
  }

  &-right {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    flex: 1;

    &-icon {
      margin-left: 12px;
      font-size: 16px;
      cursor: pointer;
      color: var(--text-color);
      transition: color 0.2s;

      &:hover {
        color: #1890ff;
      }
    }
  }
}

.table-toolbar-inner-popover-title {
  padding: 2px 0;
}

.s-table {
  width: 100%;
  overflow: auto;
  border-radius: 4px;
  background: var(--bg-color-base);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
}
</style>